﻿using System.Collections.Generic;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;
using ValidationEngine.Commons;
using ValidationEngine.Commons.Enums;
using ValidationEngine.Commons.Interfaces;

namespace ValidationEngine.Tools
{
    /// <summary>
    /// IXErrorProvider implementation
    /// </summary>
    internal class XErrorProvider : IXErrorProvider
    {
        #region Members

        private ErrorProvider _errProvider = new ErrorProvider();
        private ErrorProvider _warnProvider = new ErrorProvider();
        private ErrorProvider _infoProvider = new ErrorProvider();

        private Dictionary<Control, IValidationInfo> _controlsWithErrors = new Dictionary<Control, IValidationInfo>();

        #endregion Members

        #region Tools

        /// <summary>
        /// Initializes internal error providers. Loads error icons
        /// </summary>
        private void InitProviders()
        {
            var rm = new ResourceManager("Icons", this.GetType().Assembly);
            _errProvider.Icon = Icon.FromHandle(Resources.error.GetHicon());
            _warnProvider.Icon = Icon.FromHandle(Resources.warning.GetHicon());
            _infoProvider.Icon = Icon.FromHandle(Resources.info.GetHicon());
        }

        /// <summary>
        /// Sets appropriate error to control
        /// </summary>
        /// <param name="ctrl">Control</param>
        /// <param name="text">Message</param>
        /// <param name="extErrorType">Error type</param>
        private void SetControlMsg(Control ctrl, string text, ValidationErrorType extErrorType)
        {
            if (!_controlsWithErrors.ContainsKey(ctrl))
            {
                if (text.IsNullOrEmpty())
                {
                    return;
                }
                _controlsWithErrors.Add(ctrl, new ValidationInfo());
            }
            IValidationInfo vi = _controlsWithErrors[ctrl];
            switch (extErrorType)
            {
                case ValidationErrorType.Error:
                    vi.ClearErrors();
                    vi.AddError(text);
                    break;

                case ValidationErrorType.Warning:
                    vi.ClearWarnings();
                    vi.AddWarning(text);
                    break;

                case ValidationErrorType.Information:
                    vi.ClearInfos();
                    vi.AddInfo(text);
                    break;

                default:
                    break;
            }
            var provider = GetProvider(extErrorType);
            if (ctrl is DevExpress.XtraGrid.GridControl || ctrl is DataGridView)
            {
                provider.SetIconAlignment(ctrl, ErrorIconAlignment.MiddleLeft);
            }
            provider.SetError(ctrl, text);
            if (!text.IsNullOrEmpty() && ctrl.GetContainerControl().ActiveControl != ctrl)
            {
                ctrl.Select();
            }
        }

        /// <summary>
        /// Return according internal error provider
        /// </summary>
        /// <param name="extErrorType">Errpr type</param>
        /// <returns>Error provider</returns>
        private ErrorProvider GetProvider(ValidationErrorType extErrorType)
        {
            switch (extErrorType)
            {
                case ValidationErrorType.Error:
                    return _errProvider;

                case ValidationErrorType.Warning:
                    return _warnProvider;

                case ValidationErrorType.Information:
                    return _infoProvider;

                default:
                    return _errProvider;
            }
        }

        #endregion Tools

        #region IXErrorProvider

        public void SetError(Control ctrl, string text)
        {
            SetControlMsg(ctrl, text, ValidationErrorType.Error);
        }

        public void SetWarning(Control ctrl, string text)
        {
            SetControlMsg(ctrl, text, ValidationErrorType.Warning);
        }

        public void SetInfo(Control ctrl, string text)
        {
            SetControlMsg(ctrl, text, ValidationErrorType.Information);
        }

        public void Clear(Control ctrl)
        {
            if (_controlsWithErrors.ContainsKey(ctrl))
            {
                _controlsWithErrors.Remove(ctrl);
                _errProvider.SetError(ctrl, null);
                _warnProvider.SetError(ctrl, null);
                _infoProvider.SetError(ctrl, null);
            }
        }

        #endregion IXErrorProvider

        #region Ctor

        public XErrorProvider()
        {
            InitProviders();
        }

        #endregion Ctor
    }
}